package com.yunxin.core.domain.service.contact.impl;

import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.core.domain.external.contact.SmsGatewayService;
import com.yunxin.core.domain.external.contact.SmsSendResult;
import com.yunxin.core.domain.model.contact.*;
import com.yunxin.core.domain.service.contact.SendMessageService;
import com.yunxin.core.infra.common.contact.enums.MessageSendStatusEnum;
import com.yunxin.core.infra.common.contact.enums.MessageTypeEnum;
import com.yunxin.core.infra.common.contact.enums.SendSourceEnum;
import com.yunxin.core.utils.infra.common.constant.CoreResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * @author zero°
 * @since 2023-06-04
 */
@DS("core")
@Slf4j
@Service
@RequiredArgsConstructor
public class SendSmsMessageServiceImpl implements SendMessageService, ApplicationContextAware {

    private final ContactMessageSendSmsRepository contactMessageSendSmsRepository;

    private final SendSmsHandle sendSmsHandle;

    private final SmsGatewayService smsGatewayService;

    private static final Map<Integer, Function<SendMessage<?>, String>> METHOD_MAP = new HashMap<>();

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        METHOD_MAP.put(MessageTypeEnum.SMS_CODE.getSmsType(), this::sendSmsCode);
        METHOD_MAP.put(MessageTypeEnum.ALLOCATION_ORDER_SUCCESS.getSmsType(), this::sendAllocationOrderSuccess);
    }


    @Override
    public void sendMessage(SendMessage<?> sendMessage) {
        Function<SendMessage<?>, String> function = METHOD_MAP.get(sendMessage.getMessageType());
        if (Objects.isNull(function)) {
            log.warn("发送短信失败,短信类型不存在", sendMessage.getMessageType());
            throw new BusinessException(CoreResultCode.MESSAGE_TYPE_NOT_EXIST);
        }
        String content = function.apply(sendMessage);
        ContactMessageSendSms contactMessageSendSms = new ContactMessageSendSms();
        contactMessageSendSms.setTaskExecuteId(sendMessage.getTaskExecuteId());
        contactMessageSendSms.setReceiver(sendMessage.getReceiver().get(0));
        contactMessageSendSms.setSendStatus(1);
        contactMessageSendSms.setVersion(1L);
        contactMessageSendSmsRepository.saveContactMessageSendSms(contactMessageSendSms);
        SmsSendResult resultDTO = smsGatewayService.smsDistinct(content, sendMessage.getReceiver().get(0));
        contactMessageSendSms.setId(contactMessageSendSms.getId());
        contactMessageSendSms.setSerialNo(resultDTO.getUid());
        int successCount = 0;
        if (CharSequenceUtil.isEmpty(resultDTO.getFailReason())) {
            contactMessageSendSms.setSendStatus(MessageSendStatusEnum.SEND_SUCCESS.getStatus());
            successCount = 1;
        } else {
            contactMessageSendSms.setSendStatus(MessageSendStatusEnum.SUBMIT_FAIL.getStatus());
            contactMessageSendSms.setFailReason(resultDTO.getFailReason());
        }
        contactMessageSendSms.setEditTime(new Date());
        contactMessageSendSms.setVersion(contactMessageSendSms.getVersion() + 1);
        sendSmsHandle.sendSmsHandle(contactMessageSendSms, successCount);
    }

    @Override
    public void messageCallback(MessageCallback messageCallback) {
        ContactMessageSendSms contactMessageSendSms = contactMessageSendSmsRepository.getContactMessageSendSmsBySerialNo(messageCallback.getUid());
        int successCount = 0;
        if (Objects.nonNull(contactMessageSendSms) && MessageSendStatusEnum.SEND_SUCCESS.getStatus().equals(contactMessageSendSms.getSendStatus())) {
            if (MessageSendStatusEnum.REACH_SUCCESS.getStatus().equals(messageCallback.getStatus())) {
                contactMessageSendSms.setSendStatus(messageCallback.getStatus());
                successCount = 1;
            } else {
                contactMessageSendSms.setSendStatus(MessageSendStatusEnum.REACH_FAIL.getStatus());
                contactMessageSendSms.setFailReason(messageCallback.getStatusDesc());
            }
            contactMessageSendSms.setVersion(contactMessageSendSms.getVersion() + 1);
            contactMessageSendSms.setEditTime(new Date());
            sendSmsHandle.callbackSmsHandle(contactMessageSendSms, successCount);
        }
    }

    @Override
    public Integer sourceType() {
        return SendSourceEnum.SMS.getSourceType();
    }

    /**
     * 发送短信验证码
     * @param sendMessage sendMessage
     * @return String
     *
     */
    private String sendSmsCode(SendMessage<?> sendMessage) {
        String smsRegisterVariableDTO = (String) sendMessage.getVariable();
        return sendMessage.getMessageSubject() + String.format(sendMessage.getTemplateContent(), smsRegisterVariableDTO);
    }

    /**
     * 发送订单分配成功短信
     *
     * @param sendMessage sendMessage
     * @return String
     */
    private String sendAllocationOrderSuccess(SendMessage<?> sendMessage) {
        AllocationOrderSuccessMessage allocationOrderSuccessMessage = (AllocationOrderSuccessMessage) sendMessage.getVariable();
        return  sendMessage.getMessageSubject() + String.format(sendMessage.getTemplateContent(), allocationOrderSuccessMessage.getName(), allocationOrderSuccessMessage.getMerchantName());
    }
}
